package backend.service.worklog;

import backend.model.admin.CommuterData;
import backend.model.admin.Employee;
import backend.model.admin.Foreman;
import backend.model.admin.Team;
import backend.model.worklog.WorkLog;
import backend.service.admin.CommuterDataService;
import backend.service.base.DBModelServiceImpl;
import frontend.core.TimeTrackingWebApplication;
import shared.util.CalendarUtils;
import shared.other.TimePeriod;
import org.apache.commons.lang.time.DateUtils;
import org.hibernate.criterion.*;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class WorkLogServiceImpl extends DBModelServiceImpl<WorkLog> implements WorkLogService {

    @Override
    public Class<WorkLog> getEntityClass() {
        return WorkLog.class;
    }

    @Override
    public List<WorkLog> loadWorkLogForDateAndEmployee(Employee employee, Date date) {
        List<WorkLog> result = dbModelDao.findByNamedQueryAndParams("loadWorkLogForDateAndEmployee",
                new String[]{"employeeId", "date"}, new Object[]{employee.getId(), DateUtils.truncate(date, Calendar.DATE)});
       return result;
    }

    @Override
    public List<WorkLog> loadWorkLogForTimeInterval(Date startDate, Date endDate) {
        List<WorkLog> result = dbModelDao.findByNamedQueryAndParams("loadWorkLogForTimeInterval",
                new String[]{"startDate", "endDate"}, new Object[]{
                DateUtils.truncate(startDate, Calendar.DATE), DateUtils.truncate(endDate, Calendar.DATE)});
       return result;
    }

    @Override
    public List<WorkLog> loadWorkLogOfCommutersForTimeInterval(Date startDate, Date endDate) {
        List<WorkLog> result = dbModelDao.findByNamedQueryAndParams("loadWorkLogOfCommutersForTimeInterval",
                new String[]{"startDate", "endDate", "isCommuter"}, new Object[]{
                DateUtils.truncate(startDate, Calendar.DATE), DateUtils.truncate(endDate, Calendar.DATE), true});
        return result;
    }

    @Override
    public List<WorkLog> loadWorkLogForTimeIntervalAndEmployee(Employee employee, Date startDate, Date endDate) {
        List<WorkLog> result = dbModelDao.findByNamedQueryAndParams("loadWorkLogForTimeIntervalAndEmployee",
                new String[]{"employeeId", "startDate", "endDate"}, new Object[]{employee.getId(),
                DateUtils.truncate(startDate, Calendar.DATE), DateUtils.truncate(endDate, Calendar.DATE)});
       return result;
    }

    @Override
    public List<WorkLog> loadWorkLogForTimeIntervalAndTeam(Team team, Date startDate, Date endDate) {
        List<WorkLog> result = dbModelDao.findByNamedQueryAndParams("loadWorkLogForTimeIntervalAndTeam",
                new String[]{"teamId", "startDate", "endDate"}, new Object[]{team.getId(),
                DateUtils.truncate(startDate, Calendar.DATE), DateUtils.truncate(endDate, Calendar.DATE)});
        return result;
    }

    @Override
    public List<WorkLog> loadWorkLogForDateAndForemanList(Date date, List<Foreman> foremen) {

        List<WorkLog> result = dbModelDao.findByNamedQueryAndParams("loadWorkLogForDateAndForemanList",
                new String[]{"date", "foremenList"}, new Object[]{DateUtils.truncate(date, Calendar.DATE), foremen});
        return result;
    }

    @Override
    public WorkLog loadLatestWorkLogForEmployee(Employee employee) {
        DetachedCriteria criteria = DetachedCriteria.forClass(WorkLog.class);
        criteria.add(Restrictions.eq("employee.id", employee.getId()));
        criteria.addOrder(Order.desc("date")).addOrder(Order.desc("hours"));
        return dbModelDao.findSingleResultByCriteria(criteria);
    }

    @Override
    public void saveOrUpdateDBModel(WorkLog workLog) {
        enrichWorkLogWithIsCommuterField(workLog);
        super.saveOrUpdateDBModel(workLog);
    }

    @Override
    public void bulkSaveDBModels(Collection<WorkLog> dbModelCollection) {
        for (WorkLog workLog : dbModelCollection) {
            enrichWorkLogWithIsCommuterField(workLog);
        }
        super.bulkSaveDBModels(dbModelCollection);
    }

    private void enrichWorkLogWithIsCommuterField(WorkLog workLog) {
        CommuterDataService commuterDataService = TimeTrackingWebApplication.getBean(CommuterDataService.class);
        List<CommuterData> allCommuterDataForEmployee = commuterDataService.getAllCommuterDataForEmployee(workLog.getEmployee().getId());
        for (CommuterData commuterData : allCommuterDataForEmployee) {
            if (CalendarUtils.isDateInRange(workLog.getDate(), new TimePeriod(commuterData.getStartDate(), commuterData.getEndDate()))) {
                workLog.setIsCommuter(true);
                break;
            }
        }
    }
}
